/*
 * Copyright (c) 2011 Auzingers
 * Created by Oui-IT
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.auzingers.docsorganizer.gui;

import com.auzingers.docsorganizer.DocsOrganizerApplication;
import com.auzingers.docsorganizer.R;
import com.auzingers.docsorganizer.entity.GoogleEntry;
import com.auzingers.docsorganizer.googleapi.GoogleUtil;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/** Abstract class for all activities showing a list of goole docs. */
abstract class AbstractGoogleListActivity extends AbstractDbActivity {

    static final String TAG = DocsOrganizerApplication.APP_TAG + ".AbstractGoogleListActivity";

    /** Message that is sent for a successful download. */
    public static final int MSG_DOWNLOAD_COMPLETE = 1;

    /** Message that is sent if an error occured during the download. */
    public static final int MSG_DOWNLOAD_ERROR = 2;

    /** View that contains the spinning wheel and progress information. */
    private View spinningWheel;

    /** Image that shows the spinning wheel. */
    private ImageView refreshImage;

    /** Textview to show if the list is empty. */
    private TextView txtListEmpty;

    /** Data that is shown in the listview. */
    private List<GoogleEntry> data = new ArrayList<GoogleEntry>();

    /** Utility class that provides access to googles api, account manager etc. */
    private GoogleUtil googleUtil;

    private ListView listview;

    /** Processing flag, set to true while loading documents. */
    private boolean processing = false;

    /** Handles messages from the Google download thread - to show result, handle exceptions etc. */
    private Handler downloadHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_DOWNLOAD_COMPLETE:
                    downloadComplete();
                    break;
                case MSG_DOWNLOAD_ERROR:
                    downloadError(msg.obj, new Dialog.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    });
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initGoogleProperties();
    }

    /**
     * Hides the text that is shown if there's no data.
     */
    protected void hideEmptyText() {
        if (txtListEmpty != null) {
            txtListEmpty.setVisibility(View.GONE);
        }
    }

    protected void setSpinningWheel(View spinningWheel) {
        this.spinningWheel = spinningWheel;
    }

    protected void setRefreshImage(ImageView refreshImage) {
        this.refreshImage = refreshImage;
    }

    protected void setTxtListEmpty(TextView txtListEmpty) {
        this.txtListEmpty = txtListEmpty;
    }

    protected ListView getListView() {
        return listview;
    }

    @Override
    protected void addActionListeners() {
        super.addActionListeners();
        getListView().setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                itemSelected(position);
            }
        });
    }

    /**
     * Called if the users selects an item in the listview.
     * @param position position of the selected item
     */
    protected void itemSelected(int position) {
        //can be overwritten in subclass
    }

    /**
     * Sets the listview control.
     * @param pListview control to set
     */
    protected void setListView(ListView pListview) {
        listview = pListview;
    }

    /**
     * Convenience method to set the list adapter.
     * @param adapter adapter to set
     */
    protected void setListAdapter(ListAdapter adapter) {
        listview.setAdapter(adapter);
    }

    protected ListAdapter getListAdapter() {
        return listview.getAdapter();
    }

    /**
     * Initializes fields for access to google - this code just initializes fields, it does not
     * contact Google for login, though.
     */
    private void initGoogleProperties() {
        googleUtil = GoogleUtil.getInstance(getApplicationContext());
    }

    @Override
    protected void setupGui() {
        getListView().setDivider(null);
        getListView().setDividerHeight(0);
        getListView().setTextFilterEnabled(true);
    }

    /**
     * Starts the spinning wheel animation for downloading data from Google.
     */
    void startAnimation() {
        processing = true;
        txtListEmpty.setVisibility(View.GONE);
        spinningWheel.setVisibility(View.VISIBLE);
        refreshImage.setImageDrawable(getResources().getDrawable(R.drawable.spinning));
        final Animation rotateLoading = AnimationUtils.loadAnimation(this, R.anim.loading);
        refreshImage.clearAnimation();
        refreshImage.setAnimation(rotateLoading);
    }

    /**
     * Stops the spinning wheel animation for downloading data from Google.
     */
    void stopAnimation() {
        spinningWheel.setVisibility(View.GONE);
        refreshImage.clearAnimation();
        processing = false;
    }

    /**
     * Called when the download is complete - removes the progress information and updates the list
     * with the newly received items.
     */
    protected void downloadComplete() {
        stopAnimation();
        refreshData();
    }

    /**
     * Refreshes the data shown in the listview, updates it with the current data attribute of this instance.
     */
    protected void refreshData() {
        setListAdapter(new GoogleEntryListAdapter(this, data));
        if (txtListEmpty != null) {
            if (data.isEmpty()) {
                txtListEmpty.setVisibility(View.VISIBLE);
            } else {
                txtListEmpty.setVisibility(View.GONE);
            }
        }
    }

    /**
     * Called if an error occurs downloading data from Google - shows an Alertdialog.
     *
     * @param exception exception that has occured
     * @param okHandler handler if the user presses ok in the dialog, can be null
     */
    protected void downloadError(Object exception, Dialog.OnClickListener okHandler) {
        stopAnimation();
        final AlertDialog dlg = new AlertDialog.Builder(this).create();
        final StringBuilder msg = new StringBuilder();
        msg.append("Error downloading data. ");
        if (exception instanceof Throwable) {
            msg.append(((Throwable) exception).getLocalizedMessage());
        }
        dlg.setMessage(msg);
        dlg.setButton("Ok", okHandler);
        dlg.show();
    }

    protected GoogleUtil getGoogleUtil() {
        return googleUtil;
    }

    public boolean isProcessing() {
        return processing;
    }

    protected Handler getDownloadHandler() {
        return downloadHandler;
    }

    /**
     *  Removes all data from the internal collection.
     */
    protected void clearData() {
        data = new ArrayList<GoogleEntry>();
    }

    protected void setData(List<GoogleEntry> data) {
        this.data = data;
    }

    protected List<GoogleEntry> getData() {
        return data;
    }
}
